  1.Namenode Full GC
   
  JVM内存划分为堆内存和非堆内存，堆内存分为年轻代（Young Generation）、   老年代
(Old Generation)，非堆内存就一个永久代（Permanent Generation）。
  年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量，
Survivor两个区占小容量，默认比例是8:1:1。
  堆内存用途：存放的是对象，垃圾收集器就是收集这些对象，然后根据GC算法回收。
  非堆内存用途：永久代，也称为方法区，存储程序运行时长期存活的对象，比如类的元数据、
方法、常量、属性等。
  补充：
  JDK1.8 版本废弃了永久代，替代的是元空间（MetaSpace），元空间与永久代上类似，都是方
法区的实现，他们最大区别是：元空间并不在JVM中，而是使用本地内存。
  
 2.对象分代
   
   新生成的对象首先放到年轻代Eden区，
   当Eden空间满了，触发Minor GC，存活下来的对象移动到Survivor0区，
   Survivor0区满后触发执行Minor GC，Survivor0区存活对象移动到Suvivor1区，这样保证了一段
时间内总有一个survivor区为空。
   经过多次Minor GC仍然存活的对象移动到老年代。
   老年代存储长期存活的对象，占满时会触发Major GC（Full GC），GC期间会停止所有线程等待
GC完成，所以对响应要求高的应用尽量减少发生Major GC，避免响应超时。
   Minor GC ： 清理年轻代 
   Major GC(Full GC) ： 清理老年代，清理整个堆空间，会停止应用所有线程。
 
 3.Jstat 
   查看当前jvm内存使用以及垃圾回收情况
   jstat -gc -t 58563 1s  #显示pid是58563的垃圾回收堆的行为统计
   Timestamp       S0C    S1C    S0U     S1U     EC       EU       OC         OU 
         MC     MU   CCSC   CCSU   YGC     YGCT   FGC   FGCT     GCT
	         9751.8 12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354
             9752.8 12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354
             9753.8   12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354
             9754.8   12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354
             9755.8   12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354
             9756.9   12288.0 12288.0  0.0   0.0  158208.0  8783.6  54272.0 
   23264.6  35496.0 34743.9 4144.0 3931.8    9   0.231  2    0.123   0.354    
   
   结果解释：   
   #C即Capacity 总容量，U即Used 已使用的容量
   S0C: 当前survivor0区容量（kB）。 
   S1C: 当前survivor1区容量（kB）。
   S0U: survivor0区已使用的容量（KB） 
   S1U: survivor1区已使用的容量（KB）
   EC: Eden区的总容量（KB）  
   EU: 当前Eden区已使用的容量（KB） 
   OC: Old空间容量（kB）。 
   OU: Old区已使用的容量（KB） 
   MC: Metaspace空间容量（KB）
   MU: Metacspace使用量（KB）
   CCSC: 压缩类空间容量（kB）。
   CCSU: 压缩类空间使用（kB）。
   YGC: 新生代垃圾回收次数
   YGCT: 新生代垃圾回收时间
   FGC: 老年代 full GC垃圾回收次数
   FGCT: 老年代垃圾回收时间
   GCT: 垃圾回收总消耗时间
   开启HDFS GC详细日志输出
   编辑hadoop-env.sh
   export HADOOP_LOG_DIR=/hadoop/logs/
   增加JMX配置打印详细GC信息
   指定一个日志输出目录；注释掉之前的ops
   增加新的打印配置
   #JMX配置
   export HADOOP_JMX_OPTS="-Dcom.sun.management.jmxremote.authenticate=false -
   Dcom.sun.management.jmxremote.ssl=false"
   export HADOOP_NAMENODE_OPTS="-Dhadoop.security.logger=${HADOOP_SECURITY_LOGGER:-
   INFO,RFAS} -Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER:-INFO,NullAppender}
   $HADOOP_NAMENODE_OPTS"
   export HADOOP_DATANODE_OPTS="-Dhadoop.security.logger=ERROR,RFAS
   $HADOOP_DATANODE_OPTS"
   
   
   export NAMENODE_OPTS="-verbose:gc -XX:+PrintGCDetails -
   Xloggc:${HADOOP_LOG_DIR}/logs/hadoop-gc.log \
   -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -
   XX:+PrintGCApplicationStoppedTime \
   -server -Xms150g -Xmx150g -Xmn20g -XX:SurvivorRatio=8 -
   XX:MaxTenuringThreshold=15 \
   -XX:ParallelGCThreads=18 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -
   XX:+UseCMSCompactAtFullCollection -XX:+DisableExplicitGC -
   XX:+CMSParallelRemarkEnabled \
   -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=70 -
   XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -
   XX:CMSMaxAbortablePrecleanTime=5000   \
   -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20m -
   XX:ErrorFile=${HADOOP_LOG_DIR}/logs/hs_err.log.%p -
   XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${HADOOP_LOG_DIR}/logs/%p.hprof\"
   
   export DATENODE_OPTS="-verbose:gc -XX:+PrintGCDetails -
   Xloggc:${HADOOP_LOG_DIR}/hadoop-gc.log \
   -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -
   XX:+PrintGCApplicationStoppedTime \
   -server -Xms15g -Xmx15g -Xmn4g -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15\
   
   -XX:ParallelGCThreads=18 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -
   XX:+UseCMSCompactAtFullCollection -XX:+DisableExplicitGC -
   XX:+CMSParallelRemarkEnabled \
   -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=70 -
   XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -
   XX:CMSMaxAbortablePrecleanTime=5000   \
   -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20m -
   XX:ErrorFile=${HADOOP_LOG_DIR}/logs/hs_err.log.%p -
   XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${HADOOP_LOG_DIR}/logs/%p.hprof\"
   
   export HADOOP_NAMENODE_OPTS="$NAMENODE_OPTS $HADOOP_NAMENODE_OPTS"
   export HADOOP_DATANODE_OPTS="$DATENODE_OPTS $HADOOP_DATANODE_OPTS"
   -Xms150g -Xmx150g ：堆内存大小最大和最小都是150g
   -Xmn20g ：新生代大小为20g，等于eden+2*survivor，意味着老年代为150-20=130g。
   -XX:SurvivorRatio=8 ：Eden和Survivor的大小比值为8，意味着两个Survivor区和一个Eden区
的比值为2：8，一个Survivor占整个年轻代的1/10
   -XX:ParallelGCThreads=10 ：设置ParNew GC的线程并行数，默认为 8 +
(Runtime.availableProcessors - 8) * 5/8 ，24核机器为18。
   -XX:MaxTenuringThreshold=15 ：设置对象在年轻代的最大年龄，超过这个年龄则会晋升到老年代
   -XX:+UseParNewGC ：设置新生代使用Parallel New GC
   -XX:+UseConcMarkSweepGC ：设置老年代使用CMS GC，当此项设置时候自动设置新生代为
ParNew GC
   -XX:CMSInitiatingOccupancyFraction=70 ：
   老年代第一次占用达到该百分比时候，就会引发CMS的第一次垃圾回收周期。后继CMS GC由
HotSpot自动优化计算得到。
 
 4.GC 日志解析
   
   jstat命令输出
   ime S0C  S1C  S0U  S1U   EC    EU    OC     OU    MC  
MU  CCSC  CCSU  YGC   YGCT  FGC  FGCT   GCT 
5.7 34048.0 34048.0  0.0  34048.0 272640.0 194699.7 1756416.0  181419.9
 18304.0 17865.1 2688.0 2497.6    3   0.275  0    0.000   0.275
6.7 34048.0 34048.0 34048.0  0.0  272640.0 247555.4 1756416.0  263447.9
 18816.0 18123.3 2688.0 2523.1    4   0.359  0    0.000   0.359
7.7 34048.0 34048.0  0.0  34048.0 272640.0 257729.3 1756416.0  345109.8
 19072.0 18396.6 2688.0 2550.3    5   0.451  0    0.000   0.451
8.7 34048.0 34048.0 34048.0 34048.0 272640.0 272640.0 1756416.0  444982.5
 19456.0 18681.3 2816.0 2575.8    7   0.550  0    0.000   0.550
9.7 34048.0 34048.0 34046.7  0.0  272640.0 16777.0  1756416.0  587906.3
 20096.0 19235.1 2944.0 2631.8    8   0.720  0    0.000   0.720
10.7 34048.0 34048.0  0.0  34046.2 272640.0 80171.6  1756416.0  664913.4
 20352.0 19495.9 2944.0 2657.4    9   0.810  0    0.000   0.810
11.7 34048.0 34048.0 34048.0  0.0  272640.0 129480.8 1756416.0  745100.2
 20608.0 19704.5 2944.0 2678.4   10   0.896  0    0.000   0.896
12.7 34048.0 34048.0  0.0  34046.6 272640.0 164070.7 1756416.0  822073.7
 20992.0 19937.1 3072.0 2702.8   11   0.978  0    0.000   0.978
13.7 34048.0 34048.0 34048.0  0.0  272640.0 211949.9 1756416.0  897364.4
 21248.0 20179.6 3072.0 2728.1   12   1.087  1    0.004   1.091
14.7 34048.0 34048.0  0.0  34047.1 272640.0 245801.5 1756416.0  597362.6
 21504.0 20390.6 3072.0 2750.3   13   1.183  2    0.050   1.233
15.7 34048.0 34048.0  0.0  34048.0 272640.0 21474.1  1756416.0  757347.0
 22012.0 20792.0 3200.0 2791.0   15   1.336  2    0.050   1.386
16.7 34048.0 34048.0 34047.0  0.0  272640.0 48378.0  1756416.0  838594.4
 22268.0 21003.5 3200.0 2813.2   16   1.433  2    0.050   1.484
   
   查看GC日志输出：
   3.157: [GC (Allocation Failure) 3.157: [ParNew: 272640K->34048K(306688K),
0.0844702 secs] 272640K->69574K(2063104K), 0.0845560 secs] [Times: user=0.23
sys=0.03, real=0.09 secs]
   4.092: [GC (Allocation Failure) 4.092: [ParNew: 306688K->34048K(306688K),
0.1013723 secs] 342214K->136584K(2063104K), 0.1014307 secs] [Times: user=0.25
sys=0.05, real=0.10 secs]
   ... cut for brevity ...
   11.292: [GC (Allocation Failure) 11.292: [ParNew: 306686K->34048K(306688K),
0.0857219 secs] 971599K->779148K(2063104K), 0.0857875 secs] [Times: user=0.26
sys=0.04, real=0.09 secs]
   12.140: [GC (Allocation Failure) 12.140: [ParNew: 306688K->34046K(306688K),
0.0821774 secs] 1051788K->856120K(2063104K), 0.0822400 secs] [Times: user=0.25
sys=0.03, real=0.08 secs]
   12.989: [GC (Allocation Failure) 12.989: [ParNew: 306686K->34048K(306688K),
0.1086667 secs] 1128760K->931412K(2063104K), 0.1087416 secs] [Times: user=0.24
sys=0.04, real=0.11 secs]
   13.098: [GC (CMS Initial Mark) [1 CMS-initial-mark: 897364K(1756416K)]
936667K(2063104K), 0.0041705 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
13.102: [CMS-concurrent-mark-start]
   13.341: [CMS-concurrent-mark: 0.238/0.238 secs] [Times: user=0.36 sys=0.01,
real=0.24 secs]
   13.341: [CMS-concurrent-preclean-start]
13.350: [CMS-concurrent-preclean: 0.009/0.009 secs] [Times: user=0.03 sys=0.00,
real=0.01 secs]
   13.350: [CMS-concurrent-abortable-preclean-start]
13.878: [GC (Allocation Failure) [ParNew: 16844397K->85085K(18874368K),
0.0960456 secs]
   116885867K->100127390K(155189248K), 0.0961542 secs] [Times: user=0.14 sys=0.00,
real=0.05 secs]
   14.366: [CMS-concurrent-abortable-preclean: 0.917/1.016 secs] [Times: user=2.22
sys=0.07, real=1.01 secs]
   14.366: [GC (CMS Final Remark) [YG occupancy: 182593 K (306688 K)]14.366:
[Rescan (parallel) , 0.0291598 secs]14.395: [weak refs processing, 0.0000232
secs]14.395: [class unloading, 0.0117661 secs]14.407: [scrub symbol table,
0.0015323 secs]14.409: [scrub string table, 0.0003221 secs][1 CMS-remark:
976591K(1756416K)] 1159184K(2063104K), 0.0462010 secs] [Times: user=0.14
sys=0.00, real=0.05 secs]
   14.412: [CMS-concurrent-sweep-start]
14.633: [CMS-concurrent-sweep: 0.221/0.221 secs] [Times: user=0.37 sys=0.00,
real=0.22 secs]
   14.633: [CMS-concurrent-reset-start]
   14.636: [CMS-concurrent-reset: 0.002/0.002 secs] [Times: user=0.00 sys=0.00,
real=0.00 secs]
  1).ParNew: 16844397K->85085K(18874368K), 0.0960456 secs
其中， 16844397K 表示GC前的新生代占用量， 85085K 表示GC后的新生代占用量，GC后Eden和
一个Survivor为空，所以 85085K 也是另一个Survivor的占用量。括号中的 18874368K 是Eden+一
个被占用Survivor的总和（18g）。
  2).116885867K->100127390K(155189248K), 0.0961542 secs
其中，分别是Java堆在垃圾回收前后的大小，和Java堆大小。说明堆使用为
116885867K=111.47g，回收大小为100127390K=95.49g，堆大小为155189248K=148g（去掉
其中一个Survivor），回收了16g空间.
   使用低卡顿G1收集器
   为什么会有G1呢？
   因为并发、并行和CMS垃圾收集器都有2个共同的问题：
   老年代收集器大部分操作都必须扫描整个老年代空间（标记，清除和压缩）。这就导致了GC随着
Java堆空间而线性增加或减少
   年轻代和老年代是独立的连续内存块，所以要先决定年轻代和年老代放在虚拟地址空间的位置
   G1垃圾收集器利用分而治之的思想将堆进行分区，划分为一个个的区域。
   G1垃圾收集器将堆拆成一系列的分区，这样的话，大部分的垃圾收集操作就只在一个分区内执行，从而
避免很多GC操作在整个Java堆或者整个年轻代进行。
   编辑hadoop-env.sh
   export HADOOP_NAMENODE_OPTS="-server -Xmx220G -Xms200G -XX:+UseG1GC -
XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -
XX:+ParallelRefProcEnabled -XX:-ResizePLAB -XX:+PerfDisableSharedMem -XX:-
OmitStackTraceInFastThrow -XX:G1NewSizePercent=2 -XX:ParallelGCThreads=23 -
XX:InitiatingHeapOccupancyPercent=40 -XX:G1HeapRegionSize=32M -
XX:G1HeapWastePercent=10 -XX:G1MixedGCCountTarget=16 -verbose:gc -
XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -
XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=100M -
Xloggc:/var/log/hbase/gc.log -Dhadoop.security.logger=${HADOOP_SECURITY_LOGGER:-
INFO,RFAS} -Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER:-INFO,NullAppender}
$HADOOP_NAMENODE_OPTS"
   
   注意：如果现在采用的垃圾收集器没有问题，就不要选择G1，如果追求低停顿，可以尝试使用G1